package com.gcloud.mesh.distributedSchedule.evaluateFactor;


import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;

import com.gcloud.mesh.distributedSchedule.IEvaluateFactor;

public class EvaluateFactor {

    // 评价函数名
    private String nameId = "evaluate_factor";

    // 这四个是在不同评价指标中对总体评估状况的影响系数。目前是基于经验设定的
    // TODO: 可以基于机器学习方法来自主学习改进
    private double cpu = 1.0;
    private double mem = 1.0;
    private double storage = 1.0;
    private double bandwidth = 1.0;

    // 缩放系数，用来归一化不同维度的得分, init value means not initialized.
    protected double scaleFactor = 0.0;

    public boolean scaleFactorInit() {
        return this.scaleFactor != 0.0;
    }

    public void setScaleFactor(double val) {
        this.scaleFactor = val;
    }

    public double getScaleFactor() {
        return this.scaleFactor;
    }

    public String getId() {
        return this.nameId;
    }

    protected IEvaluateFactor.Level level;
    public IEvaluateFactor.Level getLevel() {
        return this.level;
    }

    public void setLevel(IEvaluateFactor.Level l) {
        this.level = l;
    }

    private static String[] clusterList = null;
    protected static HashMap<String, Set<Integer>> cltSort = null;

    synchronized protected HashMap<String, Set<Integer>> sort(String[] clusterIds) {

        // a simple cache.
        if (EvaluateFactor.clusterList != null && EvaluateFactor.clusterList.equals(clusterIds)) {
                if (EvaluateFactor.cltSort != null) {
                    return EvaluateFactor.cltSort;
                }
        }

        EvaluateFactor.clusterList = clusterIds;
        HashMap<String, Set<Integer>> cltSort = new HashMap<>();
        for (int i = 0; i < clusterIds.length; i++) {
            if (cltSort.containsKey(clusterIds[i])) {
                Set<Integer> lst = cltSort.get(clusterIds[i]);
                lst.add(i);
                cltSort.replace(clusterIds[i], lst);
            }
            else {
                cltSort.put(clusterIds[i], new HashSet<Integer>());
            }
        }
        EvaluateFactor.cltSort = cltSort;

        return cltSort;
    }

    public double getFixedScore(double origScore) {
        return origScore * this.scaleFactor * level.getWeight();
    }
}
